// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.linqingying.gitcode

import com.intellij.collaboration.util.resolveRelative
import com.intellij.icons.AllIcons
import com.intellij.ide.BrowserUtil
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.util.io.URLUtil
import com.intellij.util.withFragment
import git4idea.remote.hosting.HostedGitRepositoriesManager
import git4idea.remote.hosting.action.GlobalHostedGitRepositoryReferenceActionGroup
import git4idea.remote.hosting.action.HostedGitRepositoryReference
import com.linqingying.gitcode.i18n.GitCodeBundle
import com.linqingying.gitcode.icons.GitCodeIcons
import com.linqingying.gitcode.util.GCHostedRepositoriesManager
import java.net.URI

class GCOpenInBrowserActionGroup
  : GlobalHostedGitRepositoryReferenceActionGroup(GitCodeBundle.messagePointer("open.on.gitcode.action"),
                                                  GitCodeBundle.messagePointer("open.on.gitcode.action.description"),
                                                  {   GitCodeIcons.GIT_CODE_ICON }) {
  override fun repositoriesManager(project: Project): HostedGitRepositoriesManager<*> {
    return project.service<GCHostedRepositoriesManager>()
  }

  override fun getUri(repository: URI, revisionHash: String): URI =
    GCPathUtil.getWebURI(repository, revisionHash)

  override fun getUri(repository: URI, revisionHash: String, relativePath: String, lineRange: IntRange?): URI =
    GCPathUtil.getWebURI(repository, revisionHash, relativePath, lineRange)

  override fun handleReference(reference: HostedGitRepositoryReference) {
    val uri = reference.buildWebURI() ?: return
    BrowserUtil.browse(uri)
  }
}

object GCPathUtil {
  fun getWebURI(repository: URI, revisionOrBranch: String): URI =
    repository.resolveRelative("commit").resolveRelative(revisionOrBranch)

  fun getWebURI(repository: URI, revisionOrBranch: String, relativePath: String, lineRange: IntRange?): URI {
    val fileUri = repository.resolveRelative("blob").resolveRelative(revisionOrBranch).resolveRelative(URLUtil.encodePath(relativePath))

    return if (lineRange != null) {
      val fragmentBuilder = StringBuilder()
      fragmentBuilder.append("L").append(lineRange.first + 1)
      if (lineRange.last != lineRange.first) {
        fragmentBuilder.append("-L").append(lineRange.last + 1)
      }
      fileUri.withFragment(fragmentBuilder.toString())
    }
    else {
      fileUri
    }
  }
}
